package com.xbniao.gcfs.common.util;

import org.apache.commons.lang3.StringUtils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 数字金额转为大写汉字金额
 * @author WangBin
 *
 */
public class MoneyFormatTool
{
	private static final String [] pattern = {"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
	private static final String [] cPattern = {"","拾","佰","仟","万","拾","佰","仟","亿"};
	private static final String [] cfPattern = {"","角","分"};
	private static final String ZEOR = "零";

	public static void main(String [] ar) throws Exception
	{
		//System.out.println(format("987"));
		//System.out.println(format("25000000000005.999"));
		System.out.println(format("100.20"));
	}

	/**
	 * 将数字金额转为大写的汉字金额
	 * @param moneyString
	 * @return
	 */
	public static String format(String moneyString) throws Exception
	{
		// 校验输入的合法行
		checkMoneyString(moneyString);

		int dotPoint = moneyString.indexOf("."); // 判断是否为小数
		String moneyStr;

		if(dotPoint != -1)
		{
			moneyStr = moneyString.substring(0, moneyString.indexOf("."));
		}
		else
		{
			moneyStr = moneyString;
		}

		StringBuffer fraction = null;   // 小数部分的处理,以及最后的元.
		StringBuffer ms = new StringBuffer();

		for(int i = 0;i < moneyStr.length();i++)
		{
			/**
			 * 按数组的编号加入对应大写汉字
			 *
			 * 把char型数字转换成的int型数字，因为它们的ASCII码值恰好相差48
			 * 因此把char型数字减去48得到int型数字，例如'4'被转换成4
			 */
			ms.append(pattern[moneyStr.charAt(i) - 48]);
		}

		int cpCursor = 1;

		for(int j = moneyStr.length() - 1; j > 0; j--)
		{
			/**
			 * 在j之后加字符,不影响j对原字符串的相对位置
			 * 只是moneyStr.length()不断增加
			 * insert(j,"string")就在j位置处插入,j=0时为第一位
			 */
			ms.insert(j, cPattern[cpCursor]);
			cpCursor = cpCursor == 8 ? 1 : cpCursor + 1; // 亿位之后重新循环
		}

		while(ms.indexOf("零拾") != -1)
		{
			/**
			 * 当十位为零时用一个"零"代替"零拾"
			 * replace的起始于终止位置
			 */
			ms.replace(ms.indexOf("零拾"), ms.indexOf("零拾") + 2, ZEOR);
		}
		while(ms.indexOf("零佰") != -1)
		{
			// 当百位为零时,同理
			ms.replace(ms.indexOf("零佰"), ms.indexOf("零佰") + 2, ZEOR);
		}
		while(ms.indexOf("零仟") != -1)
		{
			// 同理
			ms.replace(ms.indexOf("零仟"), ms.indexOf("零仟") + 2, ZEOR);
		}
		while(ms.indexOf("零万") != -1)
		{
			// 万需保留，中文习惯
			ms.replace(ms.indexOf("零万"), ms.indexOf("零万") + 2, "万");
		}
		while(ms.indexOf("零亿") != -1)
		{
			// 同上
			ms.replace(ms.indexOf("零亿"), ms.indexOf("零亿") + 2, "亿");
		}
		while(ms.indexOf("零零") != -1)
		{
			// 有连续数位出现零，即有以下情况，此时根据习惯保留一个零即可
			ms.replace(ms.indexOf("零零"), ms.indexOf("零零") + 2, ZEOR);
		}
		while(ms.indexOf("亿万") != -1)
		{
			// 特殊情况，如:100000000,根据习惯保留高位
			ms.replace(ms.indexOf("亿万"), ms.indexOf("亿万") + 2, "亿");
		}
		while(!StringUtils.isEmpty(ms.toString()) && ms.lastIndexOf(ZEOR) == ms.length()-1)
		{
			// 当结尾为零j，不必显示,经过处理也只可能出现一个零
			ms.delete(ms.lastIndexOf(ZEOR), ms.lastIndexOf(ZEOR) + 1);
		}

		int end;

		if((dotPoint = moneyString.indexOf(".")) != -1 )
		{
			// 是小数的进入
			String fs = moneyString.substring(dotPoint + 1,moneyString.length());

			if(fs.indexOf("00") == -1 || fs.indexOf("00") >= 2)
			{
				// 若前两位小数全为零，则跳过操作，仅保留两位小数
				end = fs.length() > 2 ? 2 : fs.length();
				fraction = new StringBuffer(fs.substring(0,end));

				for(int j = 0; j < fraction.length(); j++)
				{
					// 替换大写汉字
					fraction.replace(j, j + 1, pattern[fraction.charAt(j) - 48]);
				}
				for(int i = fraction.length(); i > 0; i--)
				{
					// 插入中文标识
					fraction.insert(i, cfPattern[i]);
				}

				// 如果整数部分不为空，因为：有“0.0X”或者“0.X”的情况
				if(!StringUtils.isEmpty(ms.toString()))
				{
					// 为整数部分添加标识
					fraction.insert(0, "元");
				}
				// 如果整数部分为空，去掉第一个零
				else
				{
					if(fraction.toString().startsWith(ZEOR))
						fraction.delete(0,2);
				}
			}
			else if(!StringUtils.isEmpty(ms.toString()))
			{
				fraction = new StringBuffer("元整");
			}
		}
		else if(!StringUtils.isEmpty(ms.toString()))
		{
			fraction = new StringBuffer("元整");
		}

		// 加入小数部分
		ms.append(fraction);

		if(StringUtils.isEmpty(ms.toString()))
			throw new Exception("您输入的数额必须大于0.01");
		return ms.toString();
	}

	private static void checkMoneyString(String moneyString) throws Exception
	{
		String regex = "(([1-9][0-9]*)|(([0]\\.\\d{1,2}|[1-9][0-9]*\\.\\d{1,2})))";
		if(!match(regex, moneyString))
			throw new Exception("您输入的金额有误！必须是不能超过两位小数的正数");
	}

	/**
	 * @param regex
	 * 正则表达式字符串
	 * @param str
	 * 要匹配的字符串
	 * @return 如果str 符合 regex的正则表达式格式,返回true, 否则返回 false;
	 */
	private static boolean match(String regex, String str) {
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(str);
		return matcher.matches();
	}
}